import type {
  ConnectorsForWalletsParameters,
  Wallet,
  WalletDetailsParams,
  WalletKitWalletConnectParameters,
  WalletList
} from '../types/Wallet'
import type { CreateConnectorFn } from '@wagmi/vue'
import { isHexString } from '../utils/colors'
import { uniqueBy } from '../utils/uniqueBy'
import { omitUndefinedValues } from '../utils/omitUndefinedValues'

interface WalletListItem extends Wallet {
  index: number
  groupIndex: number
  groupName: string
}
interface GetMetaDataParameters {
  appName: string
  appDescription?: string
  appUrl?: string
  appIcon?: string
}

/**
 * 获取钱包元数据
 * @param appName
 * @param appDescription
 * @param appUrl
 * @param appIcon
 */
const getWalletConnectMetaData = ({
  appName,
  appDescription,
  appUrl,
  appIcon
}: GetMetaDataParameters): WalletKitWalletConnectParameters['metadata'] => {
  return {
    name: appName,
    description: appDescription ?? appName,
    url: appUrl ?? (typeof window !== 'undefined' ? window.location.href : ''),
    icons: [...(appIcon ? [appIcon] : [])]
  }
}

export const connectorsForWallets = (
  walletList: WalletList,
  { projectId, walletConnectParameters, appName, appDescription, appUrl, appIcon }: ConnectorsForWalletsParameters
): CreateConnectorFn[] => {
  if (!walletList.length) {
    throw new Error('未提供钱包列表!!')
  }

  for (const { wallets, groupName } of walletList) {
    if (!wallets.length) {
      throw new Error(`没有为 group： ${groupName} 提供钱包!!`)
    }
  }

  let index = -1

  // 最后呈现给@wagmi/vue createConfig 中的connectors
  const connectors: CreateConnectorFn[] = []
  // 显示出来的钱包
  const visibleWallets: WalletListItem[] = []
  // 可能隐藏的钱包
  const potentiallyHiddenWallets: WalletListItem[] = []
  // 获取钱包元数据
  const walletConnectMetaData = getWalletConnectMetaData({
    appName,
    appDescription,
    appUrl,
    appIcon
  })

  for (const [groupIndex, { groupName, wallets }] of walletList.entries()) {
    for (const createWallet of wallets) {
      index++

      // 创建钱包
      const wallet = createWallet({
        projectId,
        appName,
        appIcon,
        // 'option' 仅用于 'walletConnectWallet' 钱包
        options: {
          metadata: walletConnectMetaData,
          ...walletConnectParameters
        },
        // 其他支持 walletConnect 钱包而且不是 'walletConnectWallet' 的钱包都将含有 'walletConnectParameters' 属性
        walletConnectParameters: {
          metadata: walletConnectMetaData,
          ...walletConnectParameters
        }
      })

      // 防止 ’iconAccent' 出现非16进制的值
      if (wallet?.iconAccent && !isHexString(wallet?.iconAccent)) {
        throw new Error(`属性 \`iconAccent\` 不是十六进制值的钱包: ${wallet.name}`)
      }

      // 构造钱包列表
      const walletListItem = {
        ...wallet,
        groupIndex: groupIndex + 1,
        groupName,
        index
      }

      // 处理显隐藏钱包逻辑
      if (typeof wallet.hidden === 'function') {
        potentiallyHiddenWallets.push(walletListItem)
      } else {
        visibleWallets.push(walletListItem)
      }
    }
  }

  // 根据id融合数组中相同id的钱包对象
  const walletListItems: WalletListItem[] = uniqueBy([...visibleWallets, ...potentiallyHiddenWallets], 'id')

  for (const { createConnector, groupIndex, groupName, hidden, ...walletMeta } of walletListItems) {
    if (typeof hidden === 'function') {
      // 运行函数检查是否需要隐藏钱包
      const isHidden = hidden()

      // 如果钱包被隐藏，则退出并继续下一个列表项
      if (isHidden) {
        continue
      }
    }

    // 重构附加nkDetails属性选项兼容使用qrcode还是官方walletConnect模式
    const walletMetaData = (
      additionalWkParams?: Pick<WalletDetailsParams['nkDetails'], 'isWalletConnectModalConnector' | 'showQrModal'>
    ) => ({
      nkDetails: omitUndefinedValues({
        ...walletMeta,
        groupIndex,
        groupName,
        isWalletKitConnector: true,
        /**
         * 这些额外的参数将在 WalletKit 中使用，
         * 以合并来自 wagmi 的 'walletConnectWallet' 和 'walletConnect' 连接器，
         * 并使用 showQrModal： true。
         * 这样我们就可以让用户选择他们是想通过 QR 码连接还是打开官方 walletConnect 模式
         */
        ...(additionalWkParams ? additionalWkParams : {})
      })
    })

    // 如果发现是walletConnect钱包则附加showQrmodal和isWalletConnectModalConnector选项
    const isWalletConnectConnector = walletMeta.id === 'walletConnect'

    if (isWalletConnectConnector) {
      connectors.push(
        createConnector(
          walletMetaData({
            isWalletConnectModalConnector: true,
            showQrModal: true
          })
        )
      )
    }

    const connector = createConnector(walletMetaData())
    connectors.push(connector)
  }
  return connectors
}
